//@author A0096794H
#include "TaskList.h"

vector<Task*> TaskList::listOfTasks;
int TaskList::taskCount[NUM_TASK_TYPES];
Task* TaskList::latestTask=NULL;
TaskList::TaskList() {
	for (int i=0; i<NUM_TASK_TYPES; i++) {
		taskCount[i] = 0;
	}
}

TaskList::~TaskList() {
	for (int i=0; i<totalTaskCount(); i++) {
		delete listOfTasks[i];
	}
}

bool TaskList::isEmpty()
{
	return listOfTasks.empty();
}

int TaskList::totalTaskCount()
{
	return listOfTasks.size();
}
//@author A0099619J
Task* TaskList::getTaskAt(int index)
{
	if (index < 0 || index >= totalTaskCount()) {
		return NULL;
	}
	return listOfTasks[index];
}

Task* TaskList::getTaskOfTypeAt(TaskType type, int index)
{
	if (index < 0 || index >= taskCount[type])
		return NULL;

	if (type == DEADLINE) {
		index += taskCount[FLOATING];
	}
	if (type == TIMED) {
		index += taskCount[FLOATING] + taskCount[DEADLINE];
	}
	return getTaskAt(index);
}
//@author A0101856J
int TaskList::addTask(Task* task) {
	assert(task != NULL);

	int type = task->getTaskType();
	int start = 0, end, index;

	for (int i=0; i<type; i++) {
		start += taskCount[i];
	}
	end = start + taskCount[type];
	index = start;
	
	if (type == FLOATING) {
		index = end;
	}
	else if (type == DEADLINE) {
		DeadlineTask *newTask = (DeadlineTask*) task;
		while (index < end) {
			DeadlineTask *currTask = (DeadlineTask*) listOfTasks[index];
			if (newTask->getDueDate()  > currTask->getDueDate() ||
				newTask->getDueDate() == currTask->getDueDate() &&
				newTask->getDueTime()  > currTask->getDueTime()) {
				index++;
			}
			else break;
		}
	}
	else {
		TimedTask *newTask = (TimedTask*) task;
		while (index < end) {
			TimedTask *currTask = (TimedTask*) listOfTasks[index];
			if (newTask->getStartDate()  > currTask->getStartDate() ||
				newTask->getStartDate() == currTask->getStartDate() &&
				newTask->getStartTime()  > currTask->getStartTime()) {
				index++;
			}
			else break;
		}
	}
	latestTask=task;
	listOfTasks.insert(listOfTasks.begin() + index, task);
	taskCount[type]++;
	return SUCCESS;
}

void TaskList::updateTask(Task *oldTask, Task *newTask) {
	deleteTask(oldTask);
	addTask(newTask);
}
//@author A0099619J
Task* TaskList::deleteTaskAt(int index)
{
	if (index < 0 || index >= totalTaskCount()) {
		return NULL;
	}

	Task* deletedTask = listOfTasks[index];
	listOfTasks.erase(listOfTasks.begin() + index);

	TaskType type = deletedTask->getTaskType();
	taskCount[type]--;
	return deletedTask;
}

Task* TaskList::deleteTaskOfTypeAt(TaskType type, int index)
{
	if (index < 0 || index >= taskCount[type])
		return NULL;

	if (type == DEADLINE) {
		index += taskCount[FLOATING];
	}
	if (type == TIMED) {
		index += taskCount[FLOATING] + taskCount[DEADLINE];
	}
	return deleteTaskAt(index);
}
//@author A0101856J
Task* TaskList::deleteTask(Task* deletedTask)
{
	assert(deletedTask != NULL);
	int index = searchTask(deletedTask);
	if (index == -1) {
		return NULL;
	}
	listOfTasks.erase(listOfTasks.begin() + index);

	TaskType type = deletedTask->getTaskType();
	taskCount[type]--;
	return deletedTask;
}
//@author A0105566E
int TaskList::searchTask(Task* task) {
	int result = -1;
	for ( unsigned int i=0; i < listOfTasks.size(); i++)
	{
		if ( listOfTasks[i] == task )
		{
			result = i;
			break;
		}
	}
	return result;
}
//@author A0096794H
Task* TaskList::getLatestTask()
{
	return latestTask;
}

void TaskList::setLatestTask(Task* task)
{
	latestTask=task;
}

void TaskList::resetTask()
{
	listOfTasks.clear();
}